float4x4 WVP;
float3x3 World;

float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float specularPower;

float3 globalAmbient;
float3 lightColor;

float3 eyePosition;
float3 lightDirection;
float3 lightPosition;
float spotPower;

texture2D Texture;
sampler2D texSampler = sampler_state
{
	Texture = <Texture>;
	MinFilter = anisotropic;
	MagFilter = anisotropic;
	MipFilter = linear;
	AddressU = wrap;
	AddressV = wrap;
	MaxAnisotropy = 16;
};

struct VertexShaderInput
{
	float4 Position : POSITION0;
	float2 Texture  : TEXCOORD0;
	float3 Normal   : NORMAL0;
};

struct VertexShaderOutput
{
	float4 Position : POSITION0;
	float3 PositionO: TEXCOORD0;
	float3 Normal : TEXCOORD1;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
	VertexShaderOutput output;

	output.Position = mul(input.Position, WVP);

	output.PositionO = input.Position.xyz;

	output.Normal = input.Normal;

	return output;
}

float4 getTexture(float3 position) 
{
	float2 t = float2(position.x + position.y, position.y + position.z);
	float4 sampleA = tex2D(texSampler, t);
	t += float2(0.3, 0.923);
	float4 sampleB = tex2D(texSampler, t/3.3);
	t -= float2(0.343, 0.327);
	float4 sampleC = tex2D(texSampler, t/15.9);
	return 0.25 * sampleA + 0.45*sampleB + 0.3 * sampleC;
}

float4 PSDirectionalLight(VertexShaderOutput input) : COLOR0
{
	//Difuse
	float3 L = normalize(-lightDirection);
	float diffuseLight = max(dot(input.Normal,L), 0);
	float3 diffuse = Kd*lightColor*diffuseLight;

	//Specular
	float3 V = normalize(eyePosition - input.PositionO);
	float3 H = normalize(L + V);
	float specularLight = pow(max(dot(input.Normal,H),0),specularPower);
	if(diffuseLight<=0) specularLight=0;
	float3 specular = Ks * lightColor * specularLight;

	//sum all light components
	float3 light = diffuse + specular;

	return float4(light,1) * getTexture(input.PositionO);
}


float4 PSAmbient(VertexShaderOutput input) : COLOR0
{
	return float4(Ka*globalAmbient + Ke,1) * getTexture(input.PositionO);
}

technique Ambient
{
	pass Ambient
	{
		VertexShader = compile vs_2_0 VertexShaderFunction();
		PixelShader = compile ps_2_0 PSAmbient();
	}
}
technique Directional
{
	pass Directional
	{
		PixelShader = compile ps_2_0 PSDirectionalLight();
	}
}
technique Point
{
	pass Point
	{
		PixelShader = compile ps_2_0 PSAmbient();
	}
}
technique Spot
{
	pass Spot 
	{
		PixelShader = compile ps_2_0 PSAmbient();
	}
}